home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr49 / 303_01.zip / LIBMTCH.C < prev    next >
Text File  |  1993-04-01  |  11KB  |  465 lines

  1. /*
  2.  *    SCCS:    %W%    %G%    %U%
  3.  *    Read library files.
  4.  *
  5.  *EMACS_MODES:c
  6.  */
  7.  
  8. #include <stdio.h>
  9. #include <fcntl.h>
  10. #ifdef    COFF
  11. #include <string.h>
  12. #endif    /*  COFF  */
  13. #include <a.out.h>
  14. #include <ar.h>
  15. #include <setjmp.h>
  16. #ifdef    COFF
  17. #include <ldfcn.h>
  18. #endif    /*  COFF  */
  19. #include "unc.h"
  20.  
  21. #ifdef    COFF
  22. long    atol();
  23. #endif    /*  COFF  */
  24. long    lseek();
  25. void    bfopen(), bfclose(), nomem();
  26. void    rrell2();
  27. void    rrell2(), markmatch();
  28. #ifdef    COFF
  29. char    *malloc();
  30. #else    /*  !COFF  */
  31. char    *strchr(), *strrchr(), *strncpy(), *strcat(), *strcpy(), *malloc();
  32. #endif    /*  !COFF  */
  33. long    matchup();
  34. int    matchup();
  35. long    findstart();
  36.  
  37. char    verbose;        /*  Tell the world what we are doing  */
  38. char    *tfnam;
  39. char    *cfile;
  40. ef_fids    mainfile;
  41. struct    commit    dreltab;
  42. int    donedrel, donebrel;
  43. long    trelpos, drelpos, brelpos;
  44. #ifdef    COFF
  45. static    struct    libit    currlib = {NULL, NULL, ""};
  46. #else    /*  !COFF  */
  47. static    struct    libit    currlib = {-1, 0, -1, ""};
  48. #endif    /*  !COFF  */
  49.  
  50. void    lclash(str)
  51. char    *str;
  52. {
  53.     (void) fprintf(stderr, "Library scan failure - %s\n", str);
  54.     (void) fprintf(stderr, "Searching %s\n", cfile);
  55.     if  (currlib.lf_name[0])
  56.         (void) fprintf(stderr, "Member is %s\n", currlib.lf_name);
  57.     exit(255);
  58. }
  59.  
  60. /*
  61.  *    Find next member.
  62.  */
  63.  
  64. #ifdef    COFF
  65. long    nextmemb(filename,lfd)
  66. char *filename;
  67. #else    /*  !COFF  */
  68. long    nextmemb(lfd)
  69. #endif    /*  !COFF  */
  70. register  struct  libit     *lfd;
  71. {
  72.     struct    ar_hdr    arbuf;
  73.     
  74. #ifdef    COFF
  75.     ldaclose(lfd->ldptr2);
  76.     if (ldclose(lfd->ldptr != FAILURE))    /* end of archive */
  77.         return -1;
  78.     lfd->ldptr = ldopen(filename,lfd->ldptr);
  79.     ldahread(lfd->ldptr, (char *)&arbuf);
  80. #else    /*  !COFF  */
  81.     if  (lfd->lf_next < 0)
  82.         return    -1;
  83.     
  84.     (void) lseek(lfd->lf_fd, lfd->lf_next, 0);
  85.     if  (read(lfd->lf_fd, (char *)&arbuf, sizeof(arbuf)) != sizeof(arbuf))  {
  86.         lfd->lf_next = -1;
  87.         return    -1;
  88.     }
  89. #endif    /*  !COFF  */
  90.     (void) strncpy(lfd->lf_name, arbuf.ar_name, sizeof(lfd->lf_name));
  91. #ifdef    COFF
  92.     return 1;
  93. #else    /*  !COFF  */
  94.     lfd->lf_offset = lfd->lf_next + sizeof(arbuf);
  95.     lfd->lf_next = (lfd->lf_offset + arbuf.ar_size + 1) & ~1;
  96.     return    lfd->lf_offset;
  97. #endif    /*  !COFF  */
  98. }
  99.  
  100. /*
  101.  *    Decode a file name thus -
  102.  *
  103.  *    -lxxx decode as /lib/libxxx.a /usr/lib/libxxx.a etc
  104.  *    -Lxxx forget "lib" ".a" bit thus -Lcrt0.o
  105.  *    or read LDPATH environment var to give list of directories as sh
  106.  *    (default /lib:/usr/lib).
  107.  *
  108.  *    Alternatively treat as normal pathname.
  109.  *
  110.  *    File names may be followed by (membername) if the file is an archive,
  111.  *    thus
  112.  *
  113.  *        -lc(printf.o)
  114.  *
  115.  *    in which case the specified module is fetched.
  116.  */
  117.  
  118. struct    libit    *getfnam(str)
  119. #ifdef    COFF
  120. char    *str;    /* will be expanded to full path name if necessary */
  121. #else    /*  !COFF  */
  122. char    *str;
  123. #endif    /*  !COFF  */
  124. {
  125.     char    *bp, *ep = NULL, *pathb, *pathe, *fullpath = NULL;
  126.     static    char    *pathn;
  127.     extern    char    *getenv();
  128. #ifdef    COFF
  129.      char    magic[8];
  130.     struct    ar_hdr    arhdr;
  131.     LDFILE *ldptr;
  132.      if  ((bp = strrchr(str, '(')) != NULL &&
  133.           (ep = strrchr(str, ')')) != NULL)
  134. #else    /*  !COFF  */
  135.     long    magic;
  136.     struct    ar_hdr    arhdr;
  137.     int    fd;
  138.  
  139.     if  ((bp = strrchr(str, '(')) != NULL &&
  140.          (ep = strrchr(str, ')')) != NULL)
  141. #endif    /*  !COFF  */
  142.  
  143.         *ep = *bp = '\0';
  144.  
  145.     if  (str[0] == '-'  &&  (str[1] == 'l' || str[1] == 'L'))  {
  146.         if  (pathn == NULL)  {
  147.             if  ((pathn = getenv("LDPATH")) == NULL)
  148.                 pathn = "/lib:/usr/lib";
  149.         }
  150.         fullpath = malloc((unsigned)(strlen(pathn) + strlen(str) + 1));
  151.         if  (fullpath == NULL)
  152.             nomem();
  153.         pathb = pathn;
  154.         do  {
  155. #ifdef    COFF
  156.              pathe = strchr(pathb, ':');
  157. #else    /*  !COFF  */
  158.             pathe = strchr(pathb, ':');
  159. #endif    /*  !COFF  */
  160.             if  (*pathb == ':')
  161.                 fullpath[0] = '\0';
  162.             else  {
  163.                 if  (pathe != NULL)
  164.                     *pathe = '\0';
  165.                 (void) strcpy(fullpath, pathb);
  166.                 (void) strcat(fullpath, "/");
  167.                 if  (pathe != NULL)
  168.                     *pathe = ':';
  169.             }
  170.             if  (str[1] == 'l')
  171.                 (void) strcat(fullpath, "lib");
  172.             (void) strcat(fullpath, &str[2]);
  173.             if  (str[1] == 'l')
  174.                 (void) strcat(fullpath, ".a");
  175. #ifdef    COFF
  176.             if  ((ldptr = ldopen(fullpath, NULL)) != NULL)
  177. #else    /*  !COFF  */
  178.             if  ((fd = open(fullpath, O_RDONLY)) >= 0)
  179. #endif    /*  !COFF  */
  180.                 goto  found;
  181.             pathb = pathe + 1;
  182.         }   while  (pathe != NULL);
  183.         
  184.         (void) fprintf(stderr, "Unable to locate lib%s.a in %s\n",
  185.             &str[2], pathn);
  186.         exit(101);
  187.     }
  188. #ifdef    COFF
  189.     else  if  ((ldptr = ldopen(str, NULL)) == NULL)  {
  190. #else    /*  !COFF  */
  191.     else  if  ((fd = open(str, O_RDONLY)) < 0)  {
  192. #endif    /*  !COFF  */
  193.         (void) fprintf(stderr, "Cannot open %s\n", str);
  194.         exit(102);
  195.     }
  196.     
  197. found:
  198.  
  199. #ifdef    COFF
  200.     str = fullpath? fullpath: str;
  201.      if  (FREAD(magic, sizeof(magic),1,ldptr) != 1  ||
  202.          strcmp(magic, ARMAG) != 0)  {
  203.         if  (ep != NULL)  {
  204.             (void) fprintf(stderr, "%s is not library file\n", str);
  205. #else    /*  !COFF  */
  206.     if  ((read(fd, (char *) &magic, sizeof(magic)) != sizeof(magic)  ||
  207.         magic != ARMAG))  {
  208.         if  (ep != NULL)  {
  209.             (void) fprintf(stderr, "%s is not library file\n",
  210.                     fullpath != NULL? fullpath: str);
  211. #endif    /*  !COFF  */
  212.             exit(103);
  213.         }
  214. #ifdef    COFF
  215.         currlib.ldptr = ldptr;
  216.         currlib.ldptr2 = ldaopen(str,ldptr);
  217. #else    /*  !COFF  */
  218.         if  (fullpath != NULL)
  219.             free(fullpath);
  220.         currlib.lf_fd = fd;
  221.         currlib.lf_offset = 0;
  222.         currlib.lf_next = -1;
  223. #endif    /*  !COFF  */
  224.         currlib.lf_name[0] = '\0';
  225.         return  &currlib;
  226.     }
  227.     
  228.     /*
  229.      *    It appears to be a library file - see if we want a specific
  230.      *    one.
  231.      */
  232.     
  233.     if  (ep != NULL)  {
  234. #ifdef    COFF
  235.          char *cp;
  236.  
  237.         for  (;;)  {
  238.             if  (ldahread(ldptr,&arhdr) == FAILURE)  {
  239.                 (void) fprintf(stderr, "Cannot find member %s in %s\n",
  240.                     bp+1, str);
  241. #else    /*  !COFF  */
  242.         currlib.lf_offset = sizeof(magic) + sizeof(struct ar_hdr);
  243.         for  (;;)  {
  244.             if  (read(fd, &arhdr, sizeof(arhdr)) != sizeof(arhdr))  {
  245.                 (void) fprintf(stderr, "Cannot find member %s in %s\n",
  246.                     bp+1, fullpath?fullpath: str);
  247. #endif    /*  !COFF  */
  248.                 exit(103);
  249.             }
  250. #ifdef    COFF
  251.              for ( cp = arhdr.ar_name + sizeof(arhdr.ar_name) - 1;
  252.                  *cp == ' ';
  253.                  cp -- ) ;
  254.              if  (strncmp(bp+1, arhdr.ar_name, cp - arhdr.ar_name + 1) == 0)
  255. #else    /*  !COFF  */
  256.             if  (strncmp(bp+1, arhdr.ar_name, sizeof(arhdr.ar_name)) == 0)
  257. #endif    /*  !COFF  */
  258.                 break;
  259. #ifdef    COFF
  260.  
  261.             if (ldclose(ldptr) != FAILURE) {
  262.                 (void) fprintf(stderr, "Cannot find member %s in %s\n",
  263.                     bp+1, str);
  264.                 exit(103);
  265.             }
  266.             ldptr = ldopen(str,ldptr);
  267. #else    /*  !COFF  */
  268.             currlib.lf_offset += arhdr.ar_size + sizeof(arhdr) + 1;
  269.             currlib.lf_offset &= ~ 1;
  270.             (void) lseek(fd, (long)(currlib.lf_offset - sizeof(arhdr)), 0);
  271. #endif    /*  !COFF  */
  272.         }
  273. #ifdef    COFF
  274.         currlib.ldptr = ldptr;
  275.         currlib.ldptr2 = ldaopen(str,ldptr);
  276. #else    /*  !COFF  */
  277.         if  (fullpath != NULL)
  278.             free(fullpath);
  279.         currlib.lf_fd = fd;
  280.         currlib.lf_next = -1;
  281. #endif    /*  !COFF  */
  282.         currlib.lf_name[0] = '\0';
  283.         *bp = '(';
  284.         *ep = ')';
  285.         return    &currlib;
  286.     }
  287.     
  288.     /*
  289.      *    Otherwise point to 1st member in library.
  290.      */
  291.     
  292. #ifdef    COFF
  293.     if  (ldahread(ldptr, &arhdr) == FAILURE)  {
  294.         (void) fprintf(stderr, "Library %s empty\n", str);
  295. #else    /*  !COFF  */
  296.     if  (read(fd, &arhdr, sizeof(arhdr)) != sizeof(arhdr))  {
  297.         (void) fprintf(stderr, "Library %s empty\n", fullpath? fullpath: str);
  298. #endif    /*  !COFF  */
  299.         exit(104);
  300.     }
  301. #ifdef    COFF
  302.     currlib.ldptr = ldptr;
  303.     currlib.ldptr2 = ldaopen(str,ldptr);
  304. #else    /*  !COFF  */
  305.     if  (fullpath != NULL)
  306.         free(fullpath);
  307.     currlib.lf_offset = sizeof(magic) + sizeof(arhdr);
  308.     currlib.lf_next = currlib.lf_offset + arhdr.ar_size + 1;
  309.     currlib.lf_next &= ~1;
  310.     currlib.lf_fd = fd;
  311. #endif    /*  !COFF  */
  312.     (void) strncpy(currlib.lf_name, arhdr.ar_name, sizeof(currlib.lf_name));
  313.     return    &currlib;
  314. }
  315.  
  316. /*
  317.  *    Process library files.
  318.  */
  319.  
  320. #define    MINTEXT    6
  321.  
  322. void    lscan(nfiles, fnames)
  323. int    nfiles;
  324. char    **fnames;
  325. {
  326.     long    tstart = mainfile.ef_tbase;
  327.     ef_fids    libfile;
  328.     register  ef_fid  ll = &libfile;
  329.     register  struct  libit     *clf;
  330.     extern    symbol    dolsymb();
  331.     int    firstfile;
  332.     
  333.     for  (;  nfiles > 0;  fnames++, nfiles--)  {
  334.         clf = getfnam(*fnames);
  335.         cfile = *fnames;
  336.         firstfile = 1;
  337.         do  {
  338.             bfopen(tfnam, ll);
  339.  
  340.             /*
  341.              *    If file is garbled, silently forget it and go
  342.              *    on to the next one.
  343.              */
  344.  
  345. #ifdef    COFF
  346.             if  (!rtext(clf->ldptr, ll))
  347. #else    /*  !COFF  */
  348.             if  (rtext(clf->lf_fd, clf->lf_offset, ll) &&
  349.                  ll->ef_tsize >= MINTEXT &&
  350.                  rdata(clf->lf_fd, clf->lf_offset, ll) &&
  351.                  rrell1(clf->lf_fd, clf->lf_offset, ll) >= 0 &&
  352.                  (trelpos = matchup(&mainfile, ll, tstart))>=0)  {
  353.             if  (!rtext(clf->lf_fd, clf->lf_offset, ll))
  354. #endif    /*  !COFF  */
  355.                 goto  closeit;
  356.                 
  357.                 if  (!rsymb(clf->lf_fd, clf->lf_offset, dolsymb, ll))  {
  358.                     (void) fprintf(stderr, "Corrupt file %s\n",
  359.                             *fnames);
  360.                     exit(150);
  361.                 }
  362.                 donedrel = 0;
  363.                 donebrel = 0;
  364.                 rrell2(clf->lf_fd, clf->lf_offset, ll);
  365.                 if  (verbose)  {
  366.                     (void) fprintf(stderr, "Found: ");
  367.                     if  (clf->lf_name[0])
  368.                         (void) fprintf(stderr, "%.14s\n",
  369.                             clf->lf_name);
  370.                     else
  371.                         (void) fprintf(stderr, "%s\n", *fnames);
  372.                 }
  373.                 if  (libfile.ef_stvec != NULL)  {
  374.                     free(libfile.ef_stvec);
  375.                     libfile.ef_stvec = NULL;
  376.                     libfile.ef_stcnt = 0;
  377.                 }
  378.                 dreltab.c_int = 0;
  379.             if  (ll->ef_tsize < MINTEXT)
  380.                 goto  closeit;
  381.                 
  382. #ifdef    COFF
  383.             if  (!rdata(clf->ldptr, ll))
  384. #else    /*  !COFF  */
  385.                 /*
  386.                  *    Start looking next time round
  387.                  *    where last one left off.
  388.                  */
  389.             if  (!rdata(clf->lf_fd, clf->lf_offset, ll))
  390. #endif    /*  !COFF  */
  391.                 goto  closeit;
  392.                 
  393. #ifdef    COFF
  394.             if  (rrell1(clf->ldptr, ll) < 0)
  395. #else    /*  !COFF  */
  396.                 tstart = trelpos + libfile.ef_tsize;
  397.             if  (rrell1(clf->lf_fd, clf->lf_offset, ll) < 0)
  398. #endif    /*  !COFF  */
  399.                 goto  closeit;
  400.                 
  401.             /*
  402.              *    If first file in library, find it from
  403.              *    beginning of main file.
  404.              */
  405.             
  406.             if  (firstfile)  {
  407.                 if  ((trelpos = findstart(&mainfile, ll)) < 0)
  408.                     goto  closeit;
  409.                 firstfile = 0;
  410.             }
  411.             else   if  (!matchup(&mainfile, ll, trelpos))
  412.                     goto  closeit;
  413.             
  414.             /*
  415.              *    Found a match.
  416.              */
  417.             
  418. #ifdef    COFF
  419.             if  (!rsymb(clf->ldptr, dolsymb, ll))  {
  420. #else    /*  !COFF  */
  421.             if  (!rsymb(clf->lf_fd, clf->lf_offset, dolsymb, ll))  {
  422. #endif    /*  !COFF  */
  423.                 (void) fprintf(stderr, "Corrupt file %s\n",
  424.                             *fnames);
  425.                 exit(150);
  426.             }
  427.             
  428.             donedrel = 0;
  429.             donebrel = 0;
  430. #ifdef    COFF
  431.             rrell2(clf->ldptr, clf->ldptr2, ll);
  432. #else    /*  !COFF  */
  433.             rrell2(clf->lf_fd, clf->lf_offset, ll);
  434. #endif    /*  !COFF  */
  435.             if  (verbose)  {
  436.                 (void) fprintf(stderr, "Found: ");
  437.                 if  (clf->lf_name[0])
  438.                     (void) fprintf(stderr, "%.14s in ",
  439.                             clf->lf_name);
  440.                 (void) fprintf(stderr, "%s\n", *fnames);
  441.             }
  442.             if  (libfile.ef_stvec != NULL)  {
  443.                 free(libfile.ef_stvec);
  444.                 libfile.ef_stvec = NULL;
  445.                 libfile.ef_stcnt = 0;
  446.             }
  447.             dreltab.c_int = 0;
  448.                 
  449.             /*
  450.              *    Start looking next time round
  451.              *    where last one left off.
  452.              */
  453.             
  454.             markmatch(&mainfile, ll, trelpos);
  455.             trelpos += libfile.ef_tsize;
  456. closeit:
  457.             bfclose(ll);
  458. #ifdef    COFF
  459.         }  while  (nextmemb(cfile,clf) >= 0);
  460. #else    /*  !COFF  */
  461.         }  while  (nextmemb(clf) >= 0);
  462. #endif    /*  !COFF  */
  463.     }
  464. }
  465.